package org.rsbot.script.internal;

import java.awt.Point;
import java.util.Random;
import java.util.Vector;

public class MouseHandler
{
  public static final int DEFAULT_MOUSE_SPEED = 10;
  public static final int DEFAULT_MAX_MOVE_AFTER = 0;
  public static final int msPerBit = 105;
  public static final int reactionTime = 0;
  private static Random staticRandom = new Random();
  private final InputManager inputManager;
  private final Random random = new Random();

  private static void adaptiveMidpoints(Vector<Point> paramVector)
  {
    int i = 0;
    while (i < paramVector.size() - 1) {
      Point localPoint1 = (Point)paramVector.get(i++);
      Point localPoint2 = (Point)paramVector.get(i);
      if ((Math.abs(localPoint1.x - localPoint2.x) > 1) || (Math.abs(localPoint1.y - localPoint2.y) > 1))
        if (Math.abs(localPoint1.x - localPoint2.x) != 0) {
          double d1 = (localPoint1.y - localPoint2.y) / (localPoint1.x - localPoint2.x);
          double d2 = localPoint1.y - d1 * localPoint1.x;
          for (int k = localPoint1.x < localPoint2.x ? localPoint1.x + 1 : localPoint2.x - 1; localPoint1.x < localPoint2.x ? k < localPoint2.x : k > localPoint1.x; k += (localPoint1.x < localPoint2.x ? 1 : -1))
            paramVector.add(i++, new Point(k, (int)Math.round(d2 + d1 * k)));
        }
        else {
          for (int j = localPoint1.y < localPoint2.y ? localPoint1.y + 1 : localPoint2.y - 1; localPoint1.y < localPoint2.y ? j < localPoint2.y : j > localPoint1.y; j += (localPoint1.y < localPoint2.y ? 1 : -1))
            paramVector.add(i++, new Point(localPoint1.x, j));
        }
    }
  }

  public static Point[] applyDynamism(Point[] paramArrayOfPoint, int paramInt1, int paramInt2)
  {
    int i = paramArrayOfPoint.length;
    double d1 = paramInt1 / i;
    double d2 = paramInt2 / d1;
    int j = (int)Math.floor(i / d2);
    Point[] arrayOfPoint = new Point[j];
    double[] arrayOfDouble = gaussTable(arrayOfPoint.length);
    double d3 = 0.0D;
    for (int k = 0; k < j; k++) {
      d3 += arrayOfDouble[k];
      int m = (int)Math.floor(i * d3);
      if (m < i)
        arrayOfPoint[k] = paramArrayOfPoint[m];
      else {
        arrayOfPoint[k] = paramArrayOfPoint[(i - 1)];
      }
    }
    if (d3 < 1.0D) {
      arrayOfPoint[(j - 1)] = paramArrayOfPoint[(i - 1)];
    }
    return arrayOfPoint;
  }

  private static double nCk(int paramInt1, int paramInt2)
  {
    return fact(paramInt1) / (fact(paramInt2) * fact(paramInt1 - paramInt2));
  }

  private static double fact(int paramInt)
  {
    double d = 1.0D;
    for (int i = 1; i <= paramInt; i++) {
      d *= i;
    }
    return d;
  }

  public static long fittsLaw(double paramDouble1, double paramDouble2)
  {
    return ()(0.0D + 105.0D * Math.log10(paramDouble1 / paramDouble2 + 1.0D) / Math.log10(2.0D));
  }

  private static double gaussian(double paramDouble)
  {
    paramDouble = 10.0D * paramDouble - 5.0D;
    return 1.0D / (Math.sqrt(5.0D) * Math.sqrt(6.283185307179586D)) * Math.exp(-paramDouble * paramDouble / 20.0D);
  }

  private static double[] gaussTable(int paramInt)
  {
    double[] arrayOfDouble = new double[paramInt];
    double d1 = 1.0D / paramInt;
    double d2 = 0.0D;
    for (int i = 0; i < paramInt; i++) {
      d2 += gaussian(i * d1);
    }
    for (i = 0; i < paramInt; i++) {
      arrayOfDouble[i] = (gaussian(i * d1) / d2);
    }
    return arrayOfDouble;
  }

  public static Point[] generateControls(int paramInt1, int paramInt2, int paramInt3, int paramInt4, int paramInt5, int paramInt6)
  {
    double d1 = Math.sqrt((paramInt1 - paramInt3) * (paramInt1 - paramInt3) + (paramInt2 - paramInt4) * (paramInt2 - paramInt4));
    double d2 = Math.atan2(paramInt4 - paramInt2, paramInt3 - paramInt1);
    int i = (int)Math.floor(d1 / paramInt5);
    i = i * paramInt5 == d1 ? i - 1 : i;
    if (i <= 1) {
      i = 2;
      paramInt5 = (int)d1 / 3;
      paramInt6 = (int)d1 / 2;
    }
    Point[] arrayOfPoint = new Point[i + 2];
    arrayOfPoint[0] = new Point(paramInt1, paramInt2);
    for (int j = 1; j < i + 1; j++) {
      double d3 = paramInt5 * j;
      Point localPoint = new Point((int)(paramInt1 + d3 * Math.cos(d2)), (int)(paramInt2 + d3 * Math.sin(d2)));
      double d4 = 1.0D - (j - 1) / i;
      d4 = d4 > 0.5D ? d4 - 0.5D : d4;
      d4 += 0.25D;
      int k = (int)(paramInt6 * d4);

      localPoint.x = (int)(localPoint.x + k * 2 * staticRandom.nextDouble() - k);
      localPoint.y = (int)(localPoint.y + k * 2 * staticRandom.nextDouble() - k);
      arrayOfPoint[j] = localPoint;
    }
    arrayOfPoint[(i + 1)] = new Point(paramInt3, paramInt4);
    return arrayOfPoint;
  }

  public static Point[] generateSpline(Point[] paramArrayOfPoint)
  {
    double d1 = paramArrayOfPoint.length - 1;
    Vector localVector = new Vector();
    int i = 0;
    for (double d2 = 0.0D; d2 <= 1.0D; d2 += 0.01D) {
      double d3 = 0.0D;
      double d4 = 0.0D;
      for (double d5 = 0.0D; d5 <= d1; d5 += 1.0D) {
        double d6 = nCk((int)d1, (int)d5) * Math.pow(d2, d5) * Math.pow(1.0D - d2, d1 - d5);
        d3 += d6 * paramArrayOfPoint[(int)d5].x;
        d4 += d6 * paramArrayOfPoint[(int)d5].y;
      }
      Point localPoint = new Point((int)d3, (int)d4);
      try {
        if (!localPoint.equals(localVector.lastElement()))
          localVector.add(localPoint);
      }
      catch (Exception localException) {
        localVector.add(localPoint);
      }
      i = d2 != 1.0D ? 1 : 0;
    }
    if (i != 0) {
      localVector.add(new Point(paramArrayOfPoint[(int)d1].x, paramArrayOfPoint[(int)d1].y));
    }
    adaptiveMidpoints(localVector);
    return (Point[])localVector.toArray(new Point[localVector.size()]);
  }

  MouseHandler(InputManager paramInputManager)
  {
    this.inputManager = paramInputManager;
  }

  public void moveMouse(int paramInt1, int paramInt2, int paramInt3, int paramInt4, int paramInt5, int paramInt6, int paramInt7)
  {
    if ((paramInt4 == -1) && (paramInt5 == -1))
    {
      return;
    }if (paramInt6 <= 0) {
      paramInt6 = 1;
    }
    if (paramInt7 <= 0)
      paramInt7 = 1;
    try
    {
      if ((paramInt4 == paramInt2) && (paramInt5 == paramInt3))
        return;
      Point[] arrayOfPoint1 = generateControls(paramInt2, paramInt3, paramInt4 + this.random.nextInt(paramInt6), paramInt5 + this.random.nextInt(paramInt7), 50, 120);
      Point[] arrayOfPoint2 = generateSpline(arrayOfPoint1);
      long l = fittsLaw(Math.sqrt(Math.pow(paramInt4 - paramInt2, 2.0D) + Math.pow(paramInt5 - paramInt3, 2.0D)), 10.0D);
      Point[] arrayOfPoint3 = applyDynamism(arrayOfPoint2, (int)l, 10);
      for (Point localPoint : arrayOfPoint3) {
        this.inputManager.hopMouse(localPoint.x, localPoint.y);
        try {
          Thread.sleep(Math.max(0, paramInt1 - 2 + this.random.nextInt(4)));
        } catch (InterruptedException localInterruptedException) {
          throw new RuntimeException(localInterruptedException);
        }
      }
    }
    catch (Exception localException)
    {
    }
  }
}